/*
 * fall.c
 */
#include "libm.h"
#include "spec.h"
#include "vardecl.h"
#include "funcdecl.h"
#include "math.h"
#include "psgdef.h"

#ifndef LOCAL
#define LOCAL
#endif

/*
----------------------------------------
  落ち その1

  機体が落ちていくのを上空から見る
  落ちた機体は回転する
  背景は消す

  引数
  int which;	PLAYER1 / PLAYER2
----------------------------------------
*/
LOCAL void
Fall1(int which)
{
  register machine *mp = &Machine[which];
  float dx, dy;
  int i;

  if (mp->vector.x + mp->colvec.x > 0.0)
    dx = MIN_RAD;
  else if (mp->vector.x + mp->colvec.x < 0.0)
    dx = -MIN_RAD;
  else
    dx = 0.0;
  if (mp->vector.y + mp->colvec.y > 0.0)
    dy = MIN_RAD;
  else if (mp->vector.y + mp->colvec.y < 0.0)
    dy = -MIN_RAD;
  else
    dy = 0.0;

  dispoff(bg0);
  PSGSeOn(SE_FALL);
  FarlSetWindowClipReg(0, 0, 255, 255);
  FarlSetWindowScaleReg(128 * SCALE_PERS, 128, -128 * SCALE_PERS, 128);
  Locate[which][LZ] = 0;
  for (i = 0; i < 60; i++) {
    VSyncWait();
    mp->direct = (mp->direct + 200) % 3600;
    Locate[which][LX] += dx;
    Locate[which][LY] += dy;
    Locate[which][LZ] -= MIN_RAD * 1400;
    AGLResetCamera();
    AGLTranslateCamera(FarlFix187(Locate[which][LX]), 
                       FarlFix187(Locate[which][LY]), 
                       0);
    AGLPerspectiveCamera(0xffc0 * SCALE_PERS);
    AGLZoomCamera(CAM_ZOOM, CAM_ZOOM, 0x20);
    DrawObjects(0, 0, PLAYER1);
    DrawObjects(0, 0, PLAYER2);
    DrawGround();
    AGLShot();
  }
  AGLShot();
  for (i = 0; i < 30; i++){
    VSyncWait();
  }
  dispon(bg0);
}

/*
----------------------------------------
  落ち その2

  カメラ横から(固定)
  機体は下に落ちていく

  引数
  int which;	PLAYER1 / PLAYER2
----------------------------------------
*/
#define ROT (82)

LOCAL void
Fall2(int which)
{
  register machine *mp = &Machine[which];
  int rotx = 0, roty = 0;
  float cx, cy;
  float dx, dy;
  int i;
  int camdir;
  int dir = mp->direct;

  /* カメラ位置計算 */
  if (Locate[which][LX] > GroundEdgeLoc) {
    if (dir <= 450 || dir >= 3150) {
      roty = ROT;
    } else if (dir > 1350 && dir < 2250) {
      roty = 3600 - ROT;
    } else if (dir > 450 && dir < 1350) {
      rotx = ROT;
    } else {
      rotx = 3600 - ROT;
    }
    camdir = 0;
    cx = GroundEdgeLoc;
    cy = GroundEdgeLoc * 1.5;
  } else if (Locate[which][LX] < -GroundEdgeLoc) {
    if (dir >= 1350 && dir <= 2250) { /* 前から落ちる */
      roty = ROT;
    } else if (dir < 450 || dir > 3150) {
      roty = 3600 - ROT;
    } else if (dir > 450 && dir < 1350) {
      rotx = 3600 - ROT;
    } else {
      rotx = ROT;
    }
    camdir = 1800;
    cx = -GroundEdgeLoc;
    cy = -GroundEdgeLoc * 1.5;
  } else if (Locate[which][LY] > GroundEdgeLoc) {
    if (dir >= 450 && dir <= 1350) { /* 前から落ちる */
      rotx = ROT;
    } else if (dir > 2250 && dir < 3150) {
      rotx = 3600 - ROT;
    } else if (dir > 1350 && dir < 2250) {
      roty = ROT;
    } else {
      roty = 3600 - ROT;
    }
    camdir = 900;
    cx = -GroundEdgeLoc * 1.5;
    cy = GroundEdgeLoc;
  } else {
    if (dir >= 2250 && dir <= 3150) { /* 前から落ちる */
      roty = 3600 - ROT;
    } else if (dir > 450 && dir < 1350) {
      roty = ROT;
    } else if (dir > 1350 && dir < 2250) { 
      rotx = 3600 - ROT;
    } else {
      rotx = ROT;
    }
    camdir = 2700;
    cx = GroundEdgeLoc * 1.5;
    cy = -GroundEdgeLoc;
  }

  if (mp->vector.x + mp->colvec.x > 0.0)
    dx = MIN_RAD;
  else if (mp->vector.x + mp->colvec.x < 0.0)
    dx = -MIN_RAD;
  else
    dx = 0.0;
  if (mp->vector.y + mp->colvec.y > 0.0)
    dy = MIN_RAD;
  else if (mp->vector.y + mp->colvec.y < 0.0)
    dy = -MIN_RAD;
  else
    dy = 0.0;

  /* ウィンドウセット */
  FarlSetWindowClipReg(0, 0, 255, 255);
  FarlSetWindowScaleReg(128 * SCALE_PERS, 128, -128 * SCALE_PERS, 128);

  /* カメラリセット */
  AGLResetCamera();
  AGLTranslateCamera(FarlFix187(cx), 
                     FarlFix187(cy), 
                     0);
//                     FarlFix187(Locate[which][LZ]));
    
  /* カメラ向き変更 */
  if (camdir >= 1800)
    AGLRotateCameraZ(camdir - 1800);
  else
    AGLRotateCameraZ(camdir + 1800);
  AGLRotateCameraX(900);
  
  AGLPerspectiveCamera(0xffc0 * SCALE_PERS);
  AGLZoomCamera(CAM_ZOOM * 2, CAM_ZOOM * 2, 0x20);
  PSGSeOn(SE_FALL);

  Locate[which][LZ] = 0;
  for (i = 0; i < 30; i++) {
    VSyncWait();
    Locate[which][LX] += dx;
    Locate[which][LY] += dy;
    Locate[which][LZ] -= MIN_RAD * 40;
    DrawObjects((i * rotx) % 3600, (i * roty) % 3600, which);
    DrawObjects(0, 0, which == PLAYER1 ? PLAYER2 : PLAYER1);
    DrawGround();
    AGLShot();
  }
}

/*
========================================
  落ち判定
========================================
*/
int
IfFall()
{
  int which;

  /* 境界座標より外の位置なら落下 */
  for (which = PLAYER1; which < PLAYER_MAX; which++) {
    if (Locate[which][LX] > GroundEdgeLoc
        || Locate[which][LX] < -GroundEdgeLoc
        || Locate[which][LY] > GroundEdgeLoc
        || Locate[which][LY] < -GroundEdgeLoc
        ) {

      /* 地面にめり込まないようにずらす */
      if (Locate[which][LX] > 0
          && Locate[which][LY] < GroundEdgeLoc
          && Locate[which][LY] > -GroundEdgeLoc) {
        Locate[which][LX] += 0.1;
      }
      if (Locate[which][LX] < 0
          && Locate[which][LY] < GroundEdgeLoc
          && Locate[which][LY] > -GroundEdgeLoc) {
        Locate[which][LX] -= 0.1;
      }
      if (Locate[which][LY] > 0
          && Locate[which][LX] < GroundEdgeLoc
          && Locate[which][LX] > -GroundEdgeLoc) {
        Locate[which][LY] += 0.1;
      }
      if (Locate[which][LY] < 0
          && Locate[which][LX] < GroundEdgeLoc
          && Locate[which][LX] > -GroundEdgeLoc) {
        Locate[which][LY] -= 0.1;
      }

      /* どっちが落ちたかを記憶 */
      RasterOff(RASTER_SCROLL2);
      whichFall = which;
      if (random() & 1)
        Fall1(whichFall);
      else
        Fall2(whichFall);
      return TRUE;
    }
  }
  return FALSE;
}
